require 'csv'

require "digest/md5" # jRubyとの挙動の違い see: http://jira.codehaus.org/browse/JRUBY-3494


# GET /events/new
get '/events/new' do
  google_login_require
  erb :'events/new.html', :layout => :'layouts/events.html'
end

# POST /events/choose
post '/events/choose' do
  google_login_require
  @event = Event.new

  # 引き回し
  @csv = params[:csv]

  # ヘッダーのみ解析
  tempCsv = CSV::StringReader.new(@csv)
  csvHeader = tempCsv.shift
  @logger.debug "parsed CSV header : " + csvHeader.inspect
  @header = [["なし", -1]]
  i = 0
  # option用に詰める
  csvHeader.each do |value|
    @header << [value, i]
    i += 1
  end

  erb :'events/choose.html', :layout => :'layouts/events.html'
end

# GET /events/1.csv
get '/events/:id.csv' do
  google_login_require
  @logger.debug rails_like_parameter_log(params)
  @event = @user.events.get(params[:id])
  @visitors = @event.visitors
  response.header["Content-Type"] = 'text/x-csv'
  response.header["Content-Disposition"] = "inline; filename=#{params[:id]}.csv;"

  csv = []
  csv << @event.csv_header.chomp + ', "QRコード URL", "来場日時"'
  @visitors.each do |visitor|
    csv << visitor.csv.chomp + ', "' + visitor.qr_code + '", "' + came_stamp(visitor.came_at) + '"'
  end
  csv.join("\n")
end


# PUT /events/1.xml
# put '/events/:id.xml' do
post '/events/:id.xml' do
  basic_auth_require

  @logger.debug "enter put method handler."
  @logger.debug rails_like_parameter_log(params)

  # 結果を確認用
  @event = @user.events.get(params[:id])

  success_all = true
  unless @event.nil? and params[:userid].nil? and Array != params[:userid].class
    params[:userid].each do |key, value|
      visitor = @event.visitors.get(:user_hash => value)
      if visitor.nil?
        success_all = false
      else
        visitor.came_at = Time.now
        success_all = false unless visitor.save
      end
    end
  else
    success_all = false
  end

  @visitors = @event.visitors

  if success_all
    response.headers["Content-Type"] = 'application/xml'
    erb :'events/show.xml'
  else
    # response.headers["Content-Type"] = 'application/xml'
    # erb :'events/error.xml'

    halt 400, 'Detect error(s).'

    # format.xml  { render :xml => @event.errors, :status => :unprocessable_entity }
  end
end


# GET /events/1.xml
get '/events/:id.xml' do
  basic_auth_require
  @logger.debug rails_like_parameter_log(params)
  @event = @user.events.get(params[:id])
  @visitors = @event.visitors
  response.headers["Content-Type"] = 'application/xml'
  erb :'events/show.xml'
end


# GET /events/1
get '/events/:id' do
  google_login_require
  @logger.debug rails_like_parameter_log(params)
  begin
    @event = @user.events.get(params[:id])
    @visitors = @event.visitors
    erb :'events/show.html', :layout => :'layouts/events.html'
  rescue
    @flash[:notice] = "なにか変ですよ?"
    erb :'events/index.html', :layout => :'layouts/events.html'
  end
end


# DELETE /events/1
delete '/events/:id' do
  google_login_require
  # Railsと同じ仕組みにする
  pass unless params[:_method] == 'delete'

  @event = @user.events.get(params[:id])
  @flash[:notice] = @event.name + "を削除しました"
  @event.destroy

  redirect '/events'
end



# GET /events.xml
get '/events.xml' do
  basic_auth_require
  @events = @user.events
  response.headers["Content-Type"] = 'application/xml'
  erb :'events/index.xml'
end


# GET /events
get '/events' do
  google_login_require
  @events = @user.events
  # puts "@events : " + @events.inspect
  erb :'events/index.html', :layout => :'layouts/events.html'
end

# POST /events
post '/events' do
  google_login_require
  @event = Event.new()
  @event.user_id = @user.id
  @event.name = params[:name]

  pick_params = {:name => params[:name_column], :mail => params[:mail_column], :number => params[:number_column]}
  
  begin
    # transactionを使いたいけど、使えない。どうしよう・・・
    # Event.transaction do
    #   @event.save
    #   parse_event(params[:csv], @event, pick_params)
    # end

    @event.save
    parse_event(params[:csv], @event, pick_params)
  rescue => e
    @logger.error 'in /event: failed transaction: ' + e.inspect
    @logger.error 'back trace: ' + e.backtrace.join("¥n")
    @flash[:error] = 'イベント保存中に障害が発生しました'
    redirect '/events/new'
  else
    @flash[:notice] = 'イベントを追加しました'
    redirect '/events'
  end
end


private

# seminorParams = [{:name => "ルームA 13:00〜", :colNum => 5}, {:name => "", :colNum => 6}]
# pickparams = {:name => 1, :mail => 2, :number => 3}
def parse_event_and_seminor(csv_string, event, seminar_params, pick_params)

  # セミナー登録
  seminar_params.each do |param|
    event.seminars.create(:name => param[:name])
  end
  seminars = event.seminars.find(:all)

  parse_csv(csv_string, event, pick_params) do |csv, row, name, mail, number, user_hash|
    event.visitors.create(:csv => csv, :name => name, :mail => mail, :number => number, :user_hash => user_hash)

    seminars.each do |seminor|
      # ToDo:セミナーの参加条件を確認して、登録

    end
  end

  return true
end

# pickparams = {:name => 1, :mail => 2, :number => 3}
def parse_event(csv_string, event, pick_params)

  parse_csv(csv_string, event, pick_params) do |csv, row, name, mail, number, user_hash|
    @logger.debug "return from parseCSV, csv : " + csv + " / name : " + name + " / mail : " + mail + " / number : " + number + " / user_hash : " + user_hash
    # puts "return from parseCSV csv : " + csv + " / name : " + name + " / mail : " + mail + " / number : " + number + " / user_hash : " + user_hash
    event.visitors.create(:csv => csv, :name => name.to_s, :mail => mail.to_s, :number => number, :user_hash => user_hash)
  end

  return true
end

def parse_csv(csv_string, event, pick_params)
  csv = CSV::StringReader.new(csv_string)
  csv_lines = []
  csv_string.each_line do |line|
    csv_lines << line
  end
  event.csv_header = csv_lines[0]
  @logger.debug "csv_header : " + csv_lines[0]

  event.save

  @logger.debug "pickParams : " + pick_params.inspect
  header = csv.shift
  i = 0
  user_check_array = []
  @logger.debug "csv_string : " + csv_string

  csv.each do |row|
    i += 1
    name = ""
    mail = ""
    number = ""
    pick_params.each do |key, col_num|
      @logger.debug "param key : " + key.to_s + " / colNum : " + col_num.to_s + " / row : " + row.inspect
      case key
      when :name then
        name = row[col_num.to_i] unless col_num == "-1"
        @logger.debug "extract name: " + name
      when :mail then
        mail = row[col_num.to_i] unless col_num == "-1"
        @logger.debug "extract mail: " + mail
      when :number then
        number = row[col_num.to_i] unless col_num == "-1"
        @logger.debug "extract number: " + number
      end
    end
    user_check_hash = Digest::MD5.hexdigest(csv_lines[i]).to_s
    # 重複チェック
    unless user_check_array.include?(user_check_hash)
      user_check_array << user_check_hash
      yield(csv_lines[i], row, name, mail, number, user_check_hash)
    end
  end
end



